`include "common.svh"
module bypass #(
    parameter RF_WRITE_WIDTH = 5,
    parameter ISSUE_WIDTH = 2
) (
    input i_write_valid[RF_WRITE_WIDTH-1:0],
    input PRF_IDX i_write_prf_idx[RF_WRITE_WIDTH-1:0],
    input word_t i_write_prf_data[RF_WRITE_WIDTH-1:0],

    input i_valid[ISSUE_WIDTH-1:0],
    input ISSUE_OP i_iop[ISSUE_WIDTH-1:0],
    output i_ready,

    output o_valid[ISSUE_WIDTH-1:0],
    output ISSUE_OP o_iop[ISSUE_WIDTH-1:0],
    input o_ready,

    output o_rob_replay_valid[ISSUE_WIDTH-1:0],
    output ROB_PTR o_rob_replay_rob_idx[ISSUE_WIDTH-1:0]

);
  ISSUE_OP bypass_iop[ISSUE_WIDTH-1:0];
  assign i_ready = o_ready;
  assign o_valid = i_valid;
  assign o_iop   = bypass_iop;
  genvar gi;
  generate
    for (gi = 0; gi < ISSUE_WIDTH; gi = gi + 1) begin : BypassBlock
      wire i_fire = i_valid[gi] & i_ready;
      wire src1_need_bypass = i_fire & ~i_iop[gi].src1_valid;
      wire src2_need_bypass = i_fire & ~i_iop[gi].src2_valid;

      logic [RF_WRITE_WIDTH-1:0] capture_src1_sel, capture_src2_sel;
      always_comb begin
        integer i;
        for (i = 0; i < RF_WRITE_WIDTH; i = i + 1) begin
          capture_src1_sel[i] = i_write_valid[i] & (i_write_prf_idx[i] == i_iop[gi].rop.prs1);
          capture_src2_sel[i] = i_write_valid[i] & (i_write_prf_idx[i] == i_iop[gi].rop.prs2);
        end
      end
      word_t capture_src1, capture_src2;
      MUX_OH #(RF_WRITE_WIDTH, `WORD_BITS) mux_capture_src1 (
          .sel (capture_src1_sel),
          .din (i_write_prf_data),
          .dout(capture_src1)
      );

      MUX_OH #(RF_WRITE_WIDTH, `WORD_BITS) mux_capture_src2 (
          .sel (capture_src2_sel),
          .din (i_write_prf_data),
          .dout(capture_src2)
      );

      wire src1_bypass = |capture_src1_sel;
      wire src2_bypass = |capture_src2_sel;
      wire src1_bypass_error = src1_need_bypass ^ src1_bypass;  //src1_need_bypass & (~src1_bypass);
      wire src2_bypass_error = src2_need_bypass ^ src2_bypass;  //src2_need_bypass & (~src2_bypass);

      always_comb begin
        bypass_iop[gi] = i_iop[gi];
        if (src1_bypass) bypass_iop[gi].src1 = capture_src1;
        if (src2_bypass) bypass_iop[gi].src2 = capture_src2;
      end
      assign o_rob_replay_rob_idx[gi] = i_iop[gi].rob_idx;
      assign o_rob_replay_valid[gi]   = (src1_bypass_error | src2_bypass_error) & i_fire;
    end
  endgenerate

endmodule

